-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add withChecks step #49
Conversation
* Constructor used for pipeline by Stapler. | ||
*/ | ||
@DataBoundConstructor | ||
public WithChecksStep(final String name) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to take more than one args? cause I saw code like https://github.com/jenkinsci/workflow-cps-plugin/blob/master/src/main/java/org/jenkinsci/plugins/workflow/cps/DSL.java#L702
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes it can take more than one, normally you would use a databoundsetter for any optional parameters
Then the syntax would be:
withChecks('Tests') {
...
}
withChecks(name: 'Tests', myotherparam: 'hello') {
...
}
if there's only one mandatory field in constructor then you can omit the parameter name
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So should we make all params optional in case that in the future, some users may only want to inject a certain field like conclusion instead of name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if we do that then the user will have to specify the name in a more verbose way,
withChecks(name: 'hello')
rather than withChecks('hello')
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Specify the name wouldn't be annoying for users IMO but make it mandatory will be an issue for future changes?
Also, it seems the snippet generator will always specify name
@mrginglymus What do you think? Do you think there will be situations where you do not want to specify the name but the status (e.g. publish several checks in the same status (say in progress) but with different names in the closure)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it should be fine to be mandatory
I had a brief play with this myself and got distracted with also doing the update bits too* - I couldn't see an easy way to do it without changing the API of public abstract class ChecksPublisher {
private final Job<?, ?> job;
public ChecksPublisher(Job<?, ?> job) {
this.job = job;
}
protected abstract void doPublish(ChecksDetails details) // replaces existing `publish`
public final void publish(ChecksDetails details) {
doPublish(details);
details.getName().ifPresent(name -> job.addOrReplaceAction(new ChecksInfo(name, details.getConsclusion()));
}
public ChecksConclusion getConclusion(String checksName) {
return job.getActions(ChecksInfo.class)
.stream()
.filter(a -> a.getName().equals(checksName))
.findFirst()
.map(ChecksInfo::getConclusion)
.orElse(ChecksConclusion.None);
}
} ie, The private static final class Callback extends BodyExecutionCallback {
private static final long serialVersionUID = 1L;
private ChecksPublisher getPublisher(StepContext context) throws IOException, InterruptedException {
return ChecksPublisherFactory.fromRun(context.get(Run.class), context.get(TaskListener.class));
}
private WithCheckContext getCheckContext(StepContext context) throws IOException, InterruptedException {
return context.get(WithCheckContext.class);
}
private ChecksDetails getDetails(WithCheckContext context, ChecksConclusion conclusion) {
return new ChecksDetails.ChecksDetailsBuilder()
.withName(context.getName())
.withConclusion(conclusion)
.withStatus(ChecksStatus.COMPLETED)
.build();
}
@Override
public void onStart(StepContext context) {
try {
ChecksDetails details = new ChecksDetails.ChecksDetailsBuilder()
.withName(getCheckContext(context).getName())
.withStatus(ChecksStatus.IN_PROGRESS)
.build();
getPublisher(context).publish(details);
} catch (Exception e) {
context.onFailure(e);
}
}
@Override
public void onSuccess(StepContext context, Object result) {
try {
WithCheckContext checkContext = getCheckContext(context);
ChecksPublisher publisher = getPublisher(context);
if (publisher.getConclusion(checkContext.getName()) == ChecksConclusion.NONE) {
publisher.publish(getDetails(checkContext, ChecksConclusion.SUCCESS));
context.onSuccess(null);
}
} catch (Exception e) {
context.onFailure(e);
}
}
@Override
public void onFailure(StepContext context, Throwable t) {
try {
WithCheckContext checkContext = getCheckContext(context);
ChecksPublisher publisher = getPublisher(context);
if (t instanceof FlowInterruptedException && ((FlowInterruptedException) t).isActualInterruption()) {
publisher.publish(getDetails(checkContext, ChecksConclusion.CANCELED));
} else if (publisher.getConclusion(checkContext.getName()) != ChecksConclusion.FAILURE) {
publisher.publish(getDetails(checkContext, ChecksConclusion.FAILURE));
}
context.onFailure(t);
} catch (Exception e) {
context.onFailure(e);
}
}
} Obviously the API change is sub-optimal, but at least it only affects implementations of this API (of which we have full control :)) rather than consumers of it (which we do not :() * it's somewhat scope creep, but I wondered if the ability to update a check should be an implementation detail consumers of the checks api plugin, or something provided by it - e.g. by storing the external id associated with a checks name in this new |
Instead of storing the published checks locally, have you ever thought about query them from GitHub? Maybe use the commit: https://docs.github.com/en/free-pro-team@latest/rest/reference/checks#list-check-runs-for-a-git-reference. This needs extra requests to GitHub, but seems not a not big deal? |
Yeah, I think that would be neater for the most part - means that we're not attempting to mirror github's state and hoping we've got it right... We would still need to add a new API to the publisher though, possibly, for abstract public ChecksConclusion getConclusion(String checksName) to This could, I guess, return |
Though the comment
doesn't inspire me with confidence... |
But if we store the info of the check as an invisible action to the run, couldn't we directly resolve it in
Yeah, seems a problem; I'll test it. |
@mrginglymus I test and it actually lists check runs of the PR from a forked repo: XiongKezhi/codingstyle#13 \o/ I think the reason may be: the commits of a PR (filed from a forked repo or not) in the repository tracked by Jenkins are indeed the "pushes in the repository where the check suite or check run were created" as the GitHub doc mentions. Do you have time to double-check it? Maybe in your repos. |
That does make sense (otherwise how would you create check runs) - but then I wonder what the note is about... |
So as I see it there are two problems, each with the same two options:
For 1., I think b. (doing it within the implementation) seems like it might make more sense as it allows each implementation to have its own understanding of what 'updating' actually means, and minimises api changes for For 2., I think b. also might make sense, again in the interest of minimising changes to the API of the I might throw up a quick PR for edit: example PR here: jenkinsci/github-checks-plugin#87 |
cc @mrginglymus (cannot request your review directly in the reviewers, maybe because you are not in the jenkins org) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, just the pom suppressions should be removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good except for suppression on version
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm are we missing some documentation for this feature? what does this look like in snippet generator too?
Hooray! This is great, and will hopefully make it a lot easier to have all the plugins have overridable checks names without complicated configuration options on each. Should we add support for withChecks('Python Tests') {
publishChecks status: IN_PROGRESS
try {
sh 'pytest tests'
junit 'results.xml'
} catch (FlowInterruptedException err) {
publishChecks status: CANCELLED
throw err
} catch( Exception err) {
publishChecks status: FAILED
throw err
}
} It would also help serve as a guide to developers on how to use it. Do you think that the above pattern might be something we could build into the |
src/main/java/io/jenkins/plugins/checks/steps/WithChecksStep.java
Outdated
Show resolved
Hide resolved
I think we should.
I think we should do that and it's ok to do it in this PR? @timja And if we do that, we will set the name as a mandatory field, or we don't know what to publish when the exceptions occur. |
Yes sounds good
If you want different names then use a different closure |
What is the expected behaviour if you nest |
@@ -19,8 +19,7 @@ | |||
|
|||
<properties> | |||
<java.level>8</java.level> | |||
<revision>1.1.2</revision> | |||
<changelist>-SNAPSHOT</changelist> | |||
<revision>1.2.0</revision> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It still should be a SNAPSHOT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The sem-ver plugin will warn about compatibility if add SNAPSHOT
Seems the injected
I can directly pass the |
Not sure |
* Constructor used for pipeline by Stapler. | ||
*/ | ||
@DataBoundConstructor | ||
public WithChecksStep(final String name) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it should be fine to be mandatory
|
||
@Override | ||
public void onSuccess(final StepContext context, final Object result) { | ||
context.onSuccess(result); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the support of the callback, this step may be much more useful (but I'm not sure if that goes beyond this step's scope) than just injecting the properties: it can be used as a progress reporter for the steps in Its closure.
Then, here is an issue:
-
We cannot publish checks on success since we definitely don't want a simple success report check to overwrite what's inside the block (in the context of this API, we don't know about checks updating even if we support that in implementation).
-
If we don't publish success, however, a simple closure in which no step publishes checks using the injected name will leave the check uncompleted forever. (as said before, if the progress reporter feature goes beyond the scope, then this should the users' problem)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we don't publish success, however, a simple closure in which no step publishes checks using the injected name will leave the check uncompleted forever. (as said before, if the progress reporter feature goes beyond the scope, then this should the users' problem)
not our problem I think
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's reasonable to expect users to be responsible for sending a success message (or indeed a failure message) within their invocation of withChecks
. I did wonder about adding to the publisher API the ability to get the current conclusion (https://github.com/jenkinsci/github-checks-plugin/pull/87/files#diff-9c475e3093c11ae9324debf6c824b9c15277a027428e5c7ed60ad6ac2ac25284R131-R134) so that we could query that in onSuccess and send a generic 'success' check if nothing else was set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That seems not feasible, since in the context of the API, we don't expect the implementation to possess the ChecksDetails
alone the build, and if we take that as a users' responsible, there is no need to add the getConclusion
method only for this feature IMO.
dc89d62
to
86dc8e3
Compare
86dc8e3
to
e724c04
Compare
* Add withChecks step * Add test for WithChecksStep. * Add document and snippet generator support. * Bump version to 1.2.0 for adding ChecksInfo and WithChecksStep. * remove unused setter * Remove unused import * Add callback for withChecks. * Add consumer doc. * Remove unnessary denpendency version in pom * Improve consumer doc
Due to #49 the <changelist> tag has been removed which breaks the build. Additionally, RevApi needs to be configured to not pick up releases from the incrementals repository.
Due to #49 the <changelist> tag has been removed which breaks the build. Additionally, RevApi needs to be configured to not pick up releases from the incrementals repository.
Support `withChecks`, see jenkinsci/checks-api-plugin#49.
Linked #45
Add the name for the closure
Figuring the way to update the checks: in the independent PR of the implementation: Update checks by name github-checks-plugin#87
Testing
cc @mrginglymus @jglick